import { MyGameObject } from '/static/js/MyGameObject/base.js';

export class Player extends MyGameObject {
    // 类的构造函数，在创建Player类的实例时会被调用，接收两个参数：root（即MyGameObject对象）和info（玩家的信息）
    constructor(root, info) {
        super(); // 调用父类的构造函数
        this.root = root; // 将传入的root对象赋值给当前实例的root属性
        this.id = info.id; // 从info对象中获取玩家角色的id信息，并赋值给当前实例的id属性
        this.x = info.x; // 从info对象中获取玩家角色的初始x坐标信息，并赋值给当前实例的x属性
        this.y = info.y; // 从info对象中获取玩家角色的初始y坐标信息，并赋值给当前实例的y属性
        this.width = info.width; // 获取玩家角色的宽度信息，赋值给当前实例的width属性
        this.height = info.height; // 获取玩家角色的高度信息，赋值给当前实例的height属性
        this.color = info.color; // 获取玩家角色的颜色信息，赋值给当前实例的color属性
        this.vx = 0; // 初始化玩家角色在水平方向的速度分量为0
        this.vy = 0; // 初始化玩家角色在垂直方向的速度分量为0
        this.speedx = 400; // 定义玩家角色在水平方向的移动速度
        this.speedy = -1000; // 定义玩家角色在跳跃时的初始垂直速度
        this.ctx = this.root.game_map.ctx; // 获取游戏地图的绘图上下文对象
        this.gravity = 50; // 定义玩家角色所受的重力加速度
        this.direction = 1; // 定义玩家角色的方向，正方向为1
        this.status = 3; // 初始值为3，表示玩家角色在游戏开始时是跳跃状态
        this.pressed_Keys = this.root.game_map.controller.pressed_Keys; // 获取按键状态
        this.animations = new Map(); // 用来存放玩家每一个状态的动画
        this.frame_current_cnt = 0; // 表示当前帧数
        this.hp = 100; // 初始化玩家角色的生命值为100
        this.$hp = this.root.$kof.find(`.kof-head-hp-${this.id}>div`); // 获取玩家血量条的jQuery对象
        this.$hp_div = this.$hp.find('div'); // 获取玩家血量条中表示当前血量的jQuery对象
    }

    start() {
        // 初始化方法，可以在子类中重写以执行一些初始化操作
    }

    // 定义move方法，用于处理玩家角色的移动逻辑
    move() {
        this.vy += this.gravity; // 在垂直方向上，根据重力加速度来更新垂直速度分量

        this.x += this.vx * this.timedelta / 1000; // 更新玩家角色的水平坐标
        this.y += this.vy * this.timedelta / 1000; // 更新玩家角色的垂直坐标

        if (this.y > 450) { // 判断玩家角色是否到达地面
            this.y = 450; // 将玩家角色的垂直坐标设置为450
            this.vy = 0; // 将垂直速度分量重置为0
            if (this.status === 3)
                this.status = 0; // 如果玩家角色之前处于跳跃状态（status === 3），则将其状态设置为空闲状态（status === 0）
        }
        if (this.x < 0) { // 限制玩家角色在水平方向上的移动范围，避免超出画布左边界
            this.x = 0;
        } else if (this.x + this.width > this.root.game_map.$canvas.width()) { // 限制玩家角色在水平方向上的移动范围，避免超出画布右边界
            this.x = 1280 - this.width;
        }
    }

    // update_control 方法，用于根据按键状态更新玩家角色的控制逻辑
    update_control() {
        let w, a, d, space;
        if (this.id === 0) { // 根据玩家角色的 id 确定按键映射
            w = this.pressed_Keys.has('w'); // 玩家 1 的跳跃键
            a = this.pressed_Keys.has('a'); // 玩家 1 的向左键
            d = this.pressed_Keys.has('d'); // 玩家 1 的向右键
            space = this.pressed_Keys.has(' '); // 玩家 1 的攻击键
        } else {
            w = this.pressed_Keys.has('ArrowUp'); // 玩家 2 的跳跃键
            a = this.pressed_Keys.has('ArrowLeft'); // 玩家 2 的向左键
            d = this.pressed_Keys.has('ArrowRight'); // 玩家 2 的向右键
            space = this.pressed_Keys.has('Enter'); // 玩家 2 的攻击键
        }

        if (this.status === 0 || this.status === 1) { // 若玩家角色处于空闲或移动状态
            if (space) { // 如果按下攻击键
                this.status = 4; // 将角色状态设为攻击状态
                this.vx = 0; // 将水平速度设为0
                this.frame_current_cnt = 0; // 重置当前帧数为0
            } else if (w) { // 如果按下跳跃键
                if (d) { // 同时按下向右键
                    this.vx = this.speedx; // 设置水平速度为正方向
                } else if (a) { // 同时按下向左键
                    this.vx = -this.speedx; // 设置水平速度为负方向
                } else {
                    this.vx = 0; // 否则水平速度为0
                }
                this.vy = this.speedy; // 设置垂直速度为跳跃速度
                this.status = 3; // 状态设置为跳跃状态
            } else if (d) { // 如果按下向右键
                this.vx = this.speedx; // 设置水平速度为正方向
                this.status = 1; // 状态设置为移动状态
            } else if (a) { // 如果按下向左键
                this.vx = -this.speedx; // 设置水平速度为负方向
                this.status = 1; // 状态设置为移动状态
            } else { // 如果没有按下任何移动键
                this.vx = 0; // 水平速度为0
                this.status = 0; // 状态设置为空闲状态
            }
        }
    }

    // update_direction 方法，用于更新玩家角色的方向
    update_direction() {
        if (this.status === 6) return; // 如果玩家角色处于死亡状态，则不更新方向
        let players = this.root.players;
        if (players[0] && players[1]) { // 如果存在两个玩家
            let me = this, you = players[1 - this.id]; // 获取当前玩家和对手玩家
            if (me.x < you.x) me.direction = 1; // 如果当前玩家在左侧，则方向为正（向右）
            else me.direction = -1; // 否则方向为负（向左）
        }
    }

    // is_attack 方法，用于设置玩家角色为被攻击状态
    is_attack() {
        if (this.status === 6) return; // 如果玩家角色处于死亡状态，则不再处理被攻击逻辑

        this.status = 5; // 将状态设置为被攻击状态
        this.frame_current_cnt = 0; // 重置当前帧数为0
        this.hp = Math.max(0, this.hp - 10); // 减少玩家角色的生命值，最低为0

        this.$hp_div.animate({
            width: this.$hp.parent().width() * this.hp / 100
        }, 300);
        this.$hp.animate({
            width: this.$hp.parent().width() * this.hp / 100
        }, 600);

        if (this.hp <= 0) { // 如果生命值小于等于0
            this.status = 6; // 将状态设置为死亡状态
            this.frame_current_cnt = 0; // 重置当前帧数为0
            this.vx = 0;//死亡后速度为0
        }
    }

    // is_collision 方法，用于检测两个矩形是否发生碰撞
    is_collision(r1, r2) {
        if (Math.max(r1.x1, r2.x1) > Math.min(r1.x2, r2.x2)) return false; // 判断x轴是否有交集
        if (Math.max(r1.y1, r2.y1) > Math.min(r1.y2, r2.y2)) return false; // 判断y轴是否有交集
        return true; // 如果x轴和y轴都有交集，则发生碰撞
    }

    // update_attack 方法，用于处理玩家角色的攻击逻辑
    update_attack() {
        if (this.status === 4 && this.frame_current_cnt === 18) { // 如果玩家角色处于攻击状态且当前帧数为18
            let me = this, you = this.root.players[1 - this.id]; // 获取当前玩家和对手玩家
            let r1;
            if (this.direction > 0) { // 如果玩家角色方向为正（向右）
                r1 = {
                    x1: me.x + 120,
                    y1: me.y + 40,
                    x2: me.x + 120 + 100,
                    y2: me.y + 40 + 20,
                };
            } else { // 如果玩家角色方向为负（向左）
                r1 = {
                    x1: me.x + me.width - 120 - 100,
                    y1: me.y + 40,
                    x2: me.x + me.width - 120 - 100 + 100,
                    y2: me.y + 40 + 20,
                };
            }
            let r2 = { // 对手玩家的矩形区域
                x1: you.x,
                y1: you.y,
                x2: you.x + you.width,
                y2: you.y + you.height,
            };

            if (this.is_collision(r1, r2)) { // 如果两个矩形发生碰撞
                you.is_attack(); // 设置对手玩家为被攻击状态
            }
        }
    }

    // update 方法，用于更新玩家角色的状态
    update() {
        this.update_control(); // 更新控制逻辑
        this.move(); // 更新移动逻辑
        this.update_direction(); // 更新方向
        this.update_attack(); // 更新攻击逻辑
        this.render(); // 渲染玩家角色
    }

    // render 方法，用于渲染玩家角色
    render() {
        let status = this.status;

        if (this.status === 1 && this.direction * this.vx < 0) { // 如果玩家角色处于移动状态且方向与速度方向相反
            status = 2; // 将状态设置为向后移动状态
        }

        let obj = this.animations.get(status); // 获取当前状态的动画对象
        if (obj && obj.loaded) { // 如果动画对象存在且已加载
            if (this.direction > 0) { // 如果玩家角色方向为正（向右）
                let k = parseInt(this.frame_current_cnt / obj.frame_rate) % obj.frame_cnt; // 计算当前帧索引
                let image = obj.gif.frames[k].image; // 获取当前帧的图像
                this.ctx.drawImage(image, this.x, this.y + obj.offset_y, image.width * obj.scale, image.height * obj.scale); // 绘制图像
            } else { // 如果玩家角色方向为负（向左）
                this.ctx.save(); // 保存画布状态
                this.ctx.scale(-1, 1); // 水平翻转画布
                this.ctx.translate(-this.root.game_map.$canvas.width(), 0); // 调整画布位置

                let k = parseInt(this.frame_current_cnt / obj.frame_rate) % obj.frame_cnt; // 计算当前帧索引
                let image = obj.gif.frames[k].image; // 获取当前帧的图像

                this.ctx.drawImage(image, this.root.game_map.$canvas.width() - this.x - this.width, this.y + obj.offset_y, image.width * obj.scale, image.height * obj.scale); // 绘制翻转后的图像

                this.ctx.restore(); // 恢复画布状态
            }
        }

        if (status === 4 || status === 5 || status === 6) { // 如果玩家角色处于攻击、被攻击或死亡状态
            if (this.frame_current_cnt == obj.frame_rate * (obj.frame_cnt - 1)) { // 如果当前帧数为动画的最后一帧
                if (status === 6) {
                    this.frame_current_cnt--; // 如果玩家角色处于死亡状态，则保持最后一帧
                } else {
                    this.status = 0; // 将状态设置为空闲状态
                }
            }
        }

        this.frame_current_cnt++; // 当前帧数自增1
    }
}